const axios = require('axios');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { promisify } = require('util');
const cozeConfig = require('../config/coze.config');

class CozeService {
  constructor() {
    this.accessToken = null;
    this.tokenExpiry = null;
  }

  async createJWT() {
    try {
      const privateKey = cozeConfig.oauth.privateKey.replace(/\\n/g, '\n');
      const now = Math.floor(Date.now() / 1000);

      const header = {
        alg: 'RS256',
        typ: 'JWT',
        kid: cozeConfig.oauth.kid
      };

      const payload = {
        iss: cozeConfig.oauth.appId,
        aud: 'api.coze.cn',
        iat: now,
        exp: now + 300, // 5分钟后过期
        jti: crypto.randomBytes(16).toString('hex')
      };

      console.log('Creating JWT with payload:', payload);
      console.log('Using kid:', cozeConfig.oauth.kid);
      console.log('Using appId:', cozeConfig.oauth.appId);

      const token = jwt.sign(payload, privateKey, {
        algorithm: 'RS256',
        header
      });

      console.log('JWT created successfully');
      return token;
    } catch (error) {
      console.error('Failed to create JWT:', error);
      throw new Error('Failed to create JWT token');
    }
  }

  async getAccessToken() {
    if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) {
      console.log('Using cached access token');
      return this.accessToken;
    }

    try {
      const jwtToken = await this.createJWT();
      console.log('JWT token created, requesting access token...');
      
      const response = await axios.post('https://api.coze.cn/api/permission/oauth2/token', {
        grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        duration_seconds: 86399 // 24小时
      }, {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${jwtToken}`
        }
      });

      console.log('Access token response:', response.data);

      this.accessToken = response.data.access_token;
      this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
      return this.accessToken;
    } catch (error) {
      console.error('Failed to get access token:', error.response ? error.response.data : error);
      throw new Error('Failed to get Coze access token');
    }
  }

  async callWorkflow(workflowType, parameters) {
    try {
      // 在测试环境中返回模拟数据
      if (process.env.NODE_ENV === 'test') {
        console.log('Running in test environment, returning mock data');
        if (workflowType === 'exercise') {
          return {
            content: {
              level_1: ['天', '地', '人', '和', '为', '贵'],
              level_2: ['天地', '人和', '为贵', '和谐', '美好', '幸福'],
              level_3: ['天地人和', '为贵重要', '美好生活', '幸福快乐', '温暖如春', '和谐美满'],
              level_4: ['天地人和为贵重', '美好生活每一天', '幸福快乐永相伴', '温暖如春沐春风', '和谐美满新生活', '美丽人生新篇章']
            },
            base_chars: ['天', '地', '人', '和', '为', '贵'],
            audio_url_1: 'https://example.com/audio1.mp3',
            audio_url_2: 'https://example.com/audio2.mp3',
            audio_url_3: 'https://example.com/audio3.mp3',
            audio_url_4: 'https://example.com/audio4.mp3'
          };
        } else if (workflowType === 'shuffle') {
          return {
            content: {
              level_1: ['和', '天', '地', '人', '为', '贵'],
              level_2: ['和谐', '天地', '人和', '为贵', '美好', '幸福'],
              level_3: ['和谐美满', '天地人和', '美好生活', '温暖如春', '幸福快乐', '为贵重要'],
              level_4: ['美好生活每一天', '天地人和为贵重', '幸福快乐永相伴', '和谐美满新生活', '温暖如春沐春风', '美丽人生新篇章']
            },
            base_chars: ['天', '地', '人', '和', '为', '贵'],
            audio_url_1: 'https://example.com/audio1-new.mp3',
            audio_url_2: 'https://example.com/audio2-new.mp3',
            audio_url_3: 'https://example.com/audio3-new.mp3',
            audio_url_4: 'https://example.com/audio4-new.mp3'
          };
        } else if (workflowType === 'image') {
          return {
            image_url: 'https://example.com/reward.jpg'
          };
        }
      }

      console.log('Getting access token...');
      const token = await this.getAccessToken();
      console.log('Access token obtained');

      const workflow = cozeConfig.workflows[workflowType];
      console.log('Workflow config:', workflow);

      if (!workflow) {
        throw new Error(`Invalid workflow type: ${workflowType}`);
      }

      const requestData = {
        workflow_id: workflow.workflowId,
        bot_id: workflow.botId,
        parameters,
        is_async: false
      };

      console.log('Calling Coze API with request:', JSON.stringify(requestData, null, 2));
      console.log('Using authorization token:', `Bearer ${token.substring(0, 10)}...`);

      const response = await axios.post('https://api.coze.cn/v1/workflow/run', requestData, {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        }
      });

      console.log('Coze API complete response:', JSON.stringify(response.data, null, 2));

      if (response.data.error) {
        console.error('Coze API returned error:', response.data.error);
        throw new Error(response.data.error);
      }

      return response.data;
    } catch (error) {
      console.error(`Failed to call ${workflowType} workflow:`, error.response ? error.response.data : error);
      throw new Error(`Failed to call Coze workflow: ${error.message}`);
    }
  }

  async generateExercise(params) {
    try {
      if (!params || !params.type) {
        throw new Error('Invalid input: type is required');
      }

      const response = await this.callWorkflow('exercise', params);
      console.log('Raw Coze response:', response);

      // 解析嵌套的 JSON 字符串
      let parsedData;
      if (typeof response.data === 'string') {
        parsedData = JSON.parse(response.data);
        console.log('Parsed Coze data:', parsedData);
      }

      // 获取实际的数据
      const exerciseData = parsedData?.date || response;
      console.log('Exercise data to use:', exerciseData);

      // 从不同可能的位置获取 base_chars
      const base_chars = exerciseData.base_chars || response.base_chars || parsedData?.base_chars || [];

      // 构建返回数据
      const result = {
        content: {
          level_1: exerciseData.level_1 || exerciseData.content?.level_1 || [],
          level_2: exerciseData.level_2 || exerciseData.content?.level_2 || [],
          level_3: exerciseData.level_3 || exerciseData.content?.level_3 || [],
          level_4: exerciseData.level_4 || exerciseData.content?.level_4 || []
        },
        base_chars,
        audio_url_1: exerciseData.audio_url_1,
        audio_url_2: exerciseData.audio_url_2,
        audio_url_3: exerciseData.audio_url_3,
        audio_url_4: exerciseData.audio_url_4
      };

      console.log('Final exercise data:', result);
      return result;
    } catch (error) {
      console.error('Failed to generate exercise:', error);
      throw error;
    }
  }

  async shuffleExercise(params) {
    try {
      if (!params || !params.base_chars || !params.content) {
        throw new Error('Invalid input: base_chars and content are required');
      }

      const response = await this.callWorkflow('shuffle', params);
      return this.parseExerciseResponse(response);
    } catch (error) {
      console.error('Failed to shuffle exercise:', error);
      throw error;
    }
  }

  async generateImage() {
    try {
      const response = await this.callWorkflow('image', {
        prompt: '生成一张精美的奖励卡片，包含积极正向的学习激励文字'
      });

      // 解析嵌套的 JSON 字符串
      let parsedData;
      if (typeof response.data === 'string') {
        parsedData = JSON.parse(response.data);
        console.log('Parsed image response:', parsedData);
      }

      // 如果有嵌套的 data 对象，使用它
      const imageData = parsedData?.data || response;
      console.log('Image data to use:', imageData);

      if (!imageData.image_url) {
        throw new Error('No image URL in response');
      }

      return imageData.image_url;
    } catch (error) {
      console.error('Failed to generate image:', error);
      throw new Error('Failed to generate reward image');
    }
  }

  parseExerciseResponse(response) {
    try {
      // 解析嵌套的 JSON 字符串
      let parsedData;
      if (typeof response.data === 'string') {
        parsedData = JSON.parse(response.data);
        console.log('Parsed exercise response:', parsedData);
      }

      // 如果有嵌套的 date 对象，使用它
      const exerciseData = parsedData?.date || response;
      console.log('Exercise data to use:', exerciseData);

      return {
        content: {
          level_1: exerciseData.level_1 || [],
          level_2: exerciseData.level_2 || [],
          level_3: exerciseData.level_3 || [],
          level_4: exerciseData.level_4 || []
        },
        audio_url_1: exerciseData.audio_url_1,
        audio_url_2: exerciseData.audio_url_2,
        audio_url_3: exerciseData.audio_url_3,
        audio_url_4: exerciseData.audio_url_4
      };
    } catch (error) {
      console.error('Failed to parse exercise response:', error);
      throw new Error('Failed to parse exercise response');
    }
  }
}

// Export both the class and a singleton instance
module.exports = {
  CozeService,
  cozeService: new CozeService()
}; 